﻿using System;
using System.Collections;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services;
using Pap.Services.WorkflowEngine;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Loan.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class LoanCasesListViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        ILoanRepository _LoanRepository;
        /// <summary>
        /// 
        /// </summary>
        ILoanExecutionService _LoanExecutionService;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WfService;


        IAdministrationRepository _AdministrationRepository;
        /// <summary>
        /// Initializes a new instance of the <see cref="LoanCasesListViewModel"/> class.
        /// </summary>
        /// <param name="loanRepository">The loan repository.</param>
        /// <param name="loanExecutionService">The loan execution service.</param>
        /// <param name="workflowService">The workflow service.</param>
        public LoanCasesListViewModel(ILoanRepository loanRepository, ILoanExecutionService loanExecutionService, IWorkflowService workflowService, IAdministrationRepository AdministrationRepository)
        {
            _LoanRepository = loanRepository;
            _LoanExecutionService = loanExecutionService;
            _WfService = workflowService;
            _AdministrationRepository = AdministrationRepository;
        }

        /// <summary>
        /// Gets the loan cases.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetLoanCases()
        {
            var procecutedLoansIDs = _WfService.GetInStep(Steps.Prosecution);
            var allLoanCases = _LoanRepository.FindLoanCases(loanCase => procecutedLoansIDs.Contains(loanCase.LoanID));
            return from loanCase in allLoanCases
                   select new
                   {
                       LoanID = loanCase.CustomerLoan.LoanID,
                       LoanNumber = loanCase.CustomerLoan.LoanNumber,
                       CustomerName = loanCase.CustomerLoan.CustomerObj.CustomerName,
                       LoanDate = loanCase.CustomerLoan.LoanCreatedDate,
                       CaseNumber = loanCase.CaseNumber,
                       CaseDate = loanCase.CaseDate
                   };
        }

        /// <summary>
        /// Gets the loan debts.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <returns></returns>
        public double GetLoanDebts(Guid loanID)
        {
            var lastExecution = _LoanRepository.GetCustomerLoanByID(loanID).LoanExecutionLst.Where(ex => ex.LoanExecutionStatus).OrderBy(ex => ex.ExecutionDate).Last();
            double payments = lastExecution.LoanExecutionInstallmentsLst.SelectMany(inst => inst.LoanInstallmentPaymentLst).Select(paym => paym.PaymentAmount).Sum();
            double TotalAmount = lastExecution.LoanExecutionInstallmentsLst.Select(inst => inst.TotalInstallmentAmount).Sum();
            return Math.Round(TotalAmount - payments, 2, MidpointRounding.AwayFromZero);
        }

        /// <summary>
        /// Pays for loan.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <param name="amount">The amount.</param>
        public void PayForLoan(Guid loanID, double amount)
        {
            using (IUnitOfWork trans = ServiceLocator.Current.GetInstance<IUnitOfWork>())
            {
                var lastExecution = _LoanRepository.GetCustomerLoanByID(loanID).LoanExecutionLst.Where(ex => ex.LoanExecutionStatus).OrderBy(ex => ex.ExecutionDate).Last();
                Guid processInstID = _WfService.GetProcessInstanceIDByEntity(loanID);
                long receiptNumber = _AdministrationRepository.GetNextReceiptNumber(RegistryInfo.CommitteeID);
                _LoanExecutionService.PayForExecution(lastExecution.LoanExecutionID, amount, receiptNumber, DateTime.Now);
                _WfService.Move(ActionTypes.PayDebts, processInstID, RegistryInfo.UserID, _WfService.GetStep(processInstID).PreviousNotes, null);

                //add loan @ loanHistory
                var loanHistory = _LoanExecutionService.GetLoanHistory(lastExecution, LoanHistoryCloseTypes.Prescution, string.Empty);
                _LoanRepository.CreateCustomerLoanHistory(loanHistory);

                trans.Commit();
            }
        }
    }
}
